﻿using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Bulbs;
using JetBrains.ReSharper.Feature.Services.CSharp.Bulbs;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.LiveTemplates;
using JetBrains.ReSharper.Intentions.Extensibility;
using JetBrains.ReSharper.Intentions.Extensibility.Menu;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.ReSharper.Psi.Util;
using JetBrains.TextControl;
using JetBrains.Util;
using JetBrains.Util.Special;
using MugenMvvmToolkit.ReSharper.Infrastructure;

namespace MugenMvvmToolkit.ReSharper.ViewModels.ContextActions
{
    [ContextAction(Name = "GenerateModelPropertiesAction", Group = "C#", Priority = 10)]
    public class GenerateModelPropertiesAction : ContextActionImplBase
    {
        #region Fields

        private readonly ModelPropertyGenerator _generator;

        #endregion

        #region Constructors

        public GenerateModelPropertiesAction([NotNull] ICSharpContextActionDataProvider provider)
            : base(provider)
        {
            _generator = new ModelPropertyGenerator(provider.ElementFactory);
        }

        #endregion

        #region Implementation of IContextAction

        public override IEnumerable<IntentionAction> CreateBulbItems()
        {
            return new IBulbAction[]
            {
                new DelegateBulbAction((solution, indicator) => Execute(solution, false, false), UiResources.GenerateModelProperties),
                new DelegateBulbAction((solution, indicator) => Execute(solution, false, true), UiResources.GenerateModelPropertiesRegion),
                new DelegateBulbAction((solution, indicator) => Execute(solution, true, false), UiResources.GenerateModelPropertiesNotification),
                new DelegateBulbAction((solution, indicator) => Execute(solution, true, true), UiResources.GenerateModelPropertiesRegionNotification)
            }.ToContextAction();
        }

        /// <summary>
        ///     Check if this action is available at the constructed context.
        ///     Actions could store precalculated info in <paramref name="cache" /> to share it between different actions
        /// </summary>
        /// <returns>
        ///     true if this bulb action is available, false otherwise.
        /// </returns>
        public override bool IsAvailable(IUserDataHolder cache)
        {
            if (Provider.SelectedElement == null)
                return false;
            var currentClassDeclaration = Provider.SelectedElement.Parent as IClassDeclaration;
            if (currentClassDeclaration == null)
                return false;
            var modelClass = ToolkitExtensions
                .GetEntityModelType(currentClassDeclaration)
                .IfNotNull(type => type.GetClassType());
            if (modelClass == null)
                return false;
            _generator.Update(currentClassDeclaration, modelClass);
            return _generator.MissingProperties.Any();
        }

        private Action<ITextControl> Execute(ISolution solution, bool withNotification,
            bool wrapToRegion)
        {
            Action<ISolution, LiveTemplatesManager, ITextControl> action = _generator.Generate(withNotification, wrapToRegion);
            return control => action(solution, LiveTemplatesManager, control);
        }

        #endregion
    }
}